﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using UnityEngine;

public class FrameAnimator : MonoBehaviour
{
    [CompilerGenerated]
    private static Predicate<Clip> <>f__am$cache7;
    [CompilerGenerated]
    private static Func<Clip, string> <>f__am$cache8;
    [CompilerGenerated]
    private static Func<Clip, Clip> <>f__am$cache9;
    [SerializeField]
    private List<Clip> clips = new List<Clip>();
    private Frame lastFrame;
    private Dictionary<string, Clip> lookup = new Dictionary<string, Clip>();
    public float normalizedTime;
    private Coroutine play;
    public bool playOnEnable = true;

    public void AddClip(Clip clip)
    {
        if (clip != null)
        {
            this.clips.Add(clip);
            this.RefreshLookup();
        }
    }

    private void Awake()
    {
        this.RefreshLookup();
    }

    public bool ContainsClip(string name)
    {
        return this.lookup.ContainsKey(name);
    }

    public Clip FindClip(string name)
    {
        Clip clip = null;
        this.lookup.TryGetValue(name, out clip);
        return clip;
    }

    public Coroutine ForcePlay(Clip clip)
    {
        if (this.play != null)
        {
            base.StopCoroutine(this.play);
        }
        this.play = base.StartCoroutine(this.Play(clip));
        return this.play;
    }

    public Coroutine ForcePlay(string name)
    {
        Clip clip = this.GetClip(name);
        if (clip == null)
        {
            return null;
        }
        return this.ForcePlay(clip);
    }

    public Clip GetClip(string name)
    {
        if (!this.ContainsClip(name))
        {
            object[] args = new object[] { name };
            UnityEngine.Debug.LogWarningFormat("Could not find animation by name '{0}'", args);
            return null;
        }
        return this.lookup[name];
    }

    public List<Clip> GetClips()
    {
        return this.clips;
    }

    public bool IsPlaying(string name)
    {
        return (this.curPlayingClipName == name);
    }

    private void OnDisable()
    {
        base.StopAllCoroutines();
    }

    private void OnEnable()
    {
        if (this.playOnEnable)
        {
            this.ForcePlay(this.clips.FirstOrDefault<Clip>());
        }
    }

    [DebuggerHidden]
    private IEnumerator Play(Clip clip)
    {
        return new <Play>c__Iterator4 { clip = clip, <$>clip = clip, <>f__this = this };
    }

    public Coroutine Play(string name)
    {
        if (this.curPlayingClipName == name)
        {
            return null;
        }
        if (!this.ContainsClip(name))
        {
            return null;
        }
        return this.ForcePlay(name);
    }

    private void RefreshLookup()
    {
        if (<>f__am$cache7 == null)
        {
            <>f__am$cache7 = x => x == null;
        }
        this.clips.RemoveAll(<>f__am$cache7);
        if (<>f__am$cache8 == null)
        {
            <>f__am$cache8 = x => x.name;
        }
        if (<>f__am$cache9 == null)
        {
            <>f__am$cache9 = x => x;
        }
        this.lookup = this.clips.ToDictionary<Clip, string, Clip>(<>f__am$cache8, <>f__am$cache9, StringComparer.CurrentCultureIgnoreCase);
    }

    public void SetClips(List<Clip> clips)
    {
        this.clips = clips;
        this.RefreshLookup();
    }

    public void SetClips(params Clip[] clips)
    {
        this.SetClips(clips.ToList<Clip>());
    }

    public Clip curPlayingClip { get; private set; }

    public string curPlayingClipName
    {
        get
        {
            return ((this.curPlayingClip == null) ? null : this.curPlayingClip.name);
        }
    }

    public bool isPlaying
    {
        get
        {
            return (this.curPlayingClip != null);
        }
    }

    [CompilerGenerated]
    private sealed class <Play>c__Iterator4 : IDisposable, IEnumerator, IEnumerator<object>
    {
        internal object $current;
        internal int $PC;
        internal FrameAnimator.Clip <$>clip;
        internal List<FrameAnimator.Frame>.Enumerator <$s_46>__0;
        internal FrameAnimator <>f__this;
        internal FrameAnimator.Frame <frame>__1;
        internal FrameAnimator.Frame <frame>__3;
        internal int <i>__2;
        internal FrameAnimator.Clip clip;

        [DebuggerHidden]
        public void Dispose()
        {
            this.$PC = -1;
        }

        public bool MoveNext()
        {
            uint num = (uint) this.$PC;
            this.$PC = -1;
            switch (num)
            {
                case 0:
                    if (((this.clip != null) && (this.clip.frames != null)) && (this.clip.frames.Count != 0))
                    {
                        this.<>f__this.curPlayingClip = this.clip;
                        this.<$s_46>__0 = this.clip.frames.GetEnumerator();
                        try
                        {
                            while (this.<$s_46>__0.MoveNext())
                            {
                                this.<frame>__1 = this.<$s_46>__0.Current;
                                this.<frame>__1.isActive = false;
                            }
                        }
                        finally
                        {
                            this.<$s_46>__0.Dispose();
                        }
                        this.<i>__2 = 0;
                        while (this.<i>__2 < this.clip.frames.Count)
                        {
                            if (this.<>f__this.lastFrame != null)
                            {
                                this.<>f__this.lastFrame.isActive = false;
                            }
                            this.<frame>__3 = this.clip.frames[this.<i>__2];
                            this.<frame>__3.isActive = true;
                            this.<>f__this.lastFrame = this.<frame>__3;
                            this.$current = new WaitForSeconds(this.<frame>__3.duration);
                            this.$PC = 1;
                            return true;
                        Label_014D:
                            this.<i>__2++;
                        }
                        if (this.clip.loop)
                        {
                            this.<>f__this.ForcePlay(this.clip);
                        }
                        else
                        {
                            this.$PC = -1;
                        }
                        break;
                    }
                    break;

                case 1:
                    goto Label_014D;
            }
            return false;
        }

        [DebuggerHidden]
        public void Reset()
        {
            throw new NotSupportedException();
        }

        object IEnumerator<object>.Current
        {
            [DebuggerHidden]
            get
            {
                return this.$current;
            }
        }

        object IEnumerator.Current
        {
            [DebuggerHidden]
            get
            {
                return this.$current;
            }
        }
    }

    [Serializable]
    public class Clip
    {
        public List<FrameAnimator.Frame> frames = new List<FrameAnimator.Frame>();
        public bool loop = true;
        public string name = "Default";

        public Clip(string name, bool loop = true)
        {
            this.name = name;
            this.loop = loop;
        }

        public void AddFrame(FrameAnimator.Frame frame)
        {
            this.frames.Add(frame);
        }

        public void AddFrame(GameObject frameObject, float duration = 0.1f)
        {
            this.AddFrame(new FrameAnimator.Frame(frameObject, duration));
        }
    }

    [Serializable]
    public class Frame
    {
        public float duration = 0.1f;
        public GameObject gameObject;

        public Frame(GameObject gameObject, float duration = 0.1f)
        {
            this.gameObject = gameObject;
            this.duration = duration;
        }

        public bool isActive
        {
            get
            {
                return ((this.gameObject != null) && this.gameObject.activeSelf);
            }
            set
            {
                if (this.gameObject != null)
                {
                    this.gameObject.SetActive(value);
                }
            }
        }
    }
}

